package com.carleasoft.mps.file.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.carleasoft.mps.core.exceptions.BusinessException;
import com.carleasoft.mps.core.result.R;
import com.carleasoft.mps.core.user.ThreadUserContext;
import com.carleasoft.mps.core.user.UserCacheData;
import com.carleasoft.mps.core.utils.DateUtil;
import com.carleasoft.mps.core.utils.VideoUtil;
import com.carleasoft.mps.core.utils.file.Excel2PdfUtil;
import com.carleasoft.mps.core.utils.file.PPT2PdfUtil;
import com.carleasoft.mps.core.utils.file.Word2PdfUtil;
import com.carleasoft.mps.data.redis.JedisService;
import com.carleasoft.mps.file.bean.entity.FileManage;
import com.carleasoft.mps.file.bean.vo.FileDeleteVo;
import com.carleasoft.mps.file.bean.vo.FilePathVo;
import com.carleasoft.mps.file.bean.vo.FileUploadVo;
import com.carleasoft.mps.file.bean.vo.PartFileIndexVo;
import com.carleasoft.mps.file.common.constants.BusinessErrorEnum;
import com.carleasoft.mps.file.common.constants.Constants;
import com.carleasoft.mps.file.common.constants.ContentTypeEnum;
import com.carleasoft.mps.file.common.util.FastdfsUtil;
import com.carleasoft.mps.file.mapper.FileManageMapper;
import com.carleasoft.mps.file.service.FileManageService;

import com.carleasoft.mps.utils.MinioUtils;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import io.minio.*;
import io.minio.messages.Item;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import com.github.tobato.fastdfs.domain.fdfs.FileInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * <p>Description: 文件 serviceImpl </p>
 *
 * @author wangxiao
 * @since 2020/5/14
 */
@Service
@Slf4j
@Transactional
public class FileManageServiceImpl extends ServiceImpl<FileManageMapper, FileManage> implements FileManageService {
    @Autowired
    private MinioClient minioClient;
    @Value("${minio.bucketName}")
    private String bucketName;

    @Autowired
    private FileManageService fileManageService;
    @Autowired
    private FastdfsUtil fastdfsUtil;
    @Autowired
    private JedisService jedisService;
    @Value("${full-path}")
    private String fullPath;

    @Autowired
    private MinioUtils minioUtils;

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public FileUploadVo upload(MultipartFile multipartFile) throws Exception {
        int index = multipartFile.getOriginalFilename().lastIndexOf(StrUtil.DOT);

        String fileName;
        String fileSuffix = null;
        if (index > 0) {
            fileName = multipartFile.getOriginalFilename().substring(0, index);
            fileSuffix = multipartFile.getOriginalFilename().substring(index);
        } else {
            fileName = multipartFile.getOriginalFilename();
        }
        String filePath = fastdfsUtil.upload(multipartFile);
        FileManage fileManage = createFileInfo(fileName, fileSuffix, filePath, null);
        FileUploadVo fileUploadVo = this.buildFileVo(fileManage);
        if (StrUtil.isNotBlank(fileSuffix)) {
            if (ContentTypeEnum.videoType(fileSuffix)) {
                this.videoUpload(multipartFile, fileUploadVo);
            }
        }

        return fileUploadVo;
    }

    public void videoUpload(MultipartFile multipartFile, FileUploadVo fileUploadVo) {
        //视频上传,计算大小,截图
        //大小
        try {
            String videoTime = VideoUtil.getVideoTime(multipartFile);
            //获取截图
            MultipartFile frame = VideoUtil.fetchFrame(multipartFile);
            String filePath = fastdfsUtil.upload(frame);
            createFileInfo(multipartFile.getOriginalFilename(), ".png", filePath, null);
            fileUploadVo.setFileSize(String.valueOf(multipartFile.getSize()));
            fileUploadVo.setFrameFilePath(filePath);
            // 加
            fileUploadVo.setVodioDurationTime(videoTime);
            Long secodes = DateUtil.getHours(videoTime);
            fileUploadVo.setVodioDuration(secodes);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public FileUploadVo savePdf(String fileId) throws Exception {
        String pdfFileId = fileId + "-01";
        FileManage fileManage;

        fileManage = new FileManage();

        fileManage = this.getById(pdfFileId);

        if (Objects.isNull(fileManage)) {
            fileManage = this.dfsDownload(fileId);
            //获取响应对象
            //从文件服务器获取文件数据
            byte[] pdf = this.getPDF(fastdfsUtil.download(fileManage.getFilePath()), fileManage.getFileSuffix());
            InputStream inputStream = new ByteArrayInputStream(pdf);
            String filePath = fastdfsUtil.upload("pdf", (long) pdf.length, inputStream);
            fileManage = createFileInfo(fileManage.getFileName(), ".pdf", filePath, pdfFileId);
        }
        return this.buildFileVo(fileManage);
    }

    /**
     * 流转成PDF
     */
    public byte[] getPDF(byte[] in, String fileSuffix) {
        try {
            switch (fileSuffix) {
                case ".doc":
                case ".docx":
                case ".txt":
                    return Word2PdfUtil.wordBytes2PdfBytes(in);
                case ".xls":
                case ".xlsx":
                    return Excel2PdfUtil.excelBytes2PdfBytes(in);
                case ".ppt":
                case ".pptx":
                    return PPT2PdfUtil.pptBytes2PdfBytes(in);
                case ".pdf":
                    return null;
                default:
                    throw new BusinessException(BusinessErrorEnum.TO_PDF_ERROR);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;

    }

    /**
     * 构建返回值数据类型
     *
     * @param fileManage
     * @return
     */
    private FileUploadVo buildFileVo(FileManage fileManage) {
        FileUploadVo fileUploadVo = BeanUtil.copyProperties(fileManage, FileUploadVo.class);
        return fileUploadVo;
    }

    /**
     * 批量上传文件
     *
     * @param multipartFiles
     * @return
     * @throws Exception
     */
    @Override
    public List<FileUploadVo> uploadFiles(MultipartFile[] multipartFiles) throws Exception {
        List<FileUploadVo> uploadVoList = new ArrayList<>();
        for (MultipartFile multipartFile : multipartFiles) {
            FileUploadVo upload = upload(multipartFile);
            uploadVoList.add(upload);
        }
        return uploadVoList;
    }


    @Override
    public void download(String fileId) throws IOException {
        FileManage fileManage = this.dfsDownload(fileId);
        //文件下载名
        String downloadName = fileManage.getFileName() + fileManage.getFileSuffix();
        //从文件服务器获取文件数据
        byte[] data = fastdfsUtil.download(fileManage.getFilePath());
        //获取响应对象
        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        response.setCharacterEncoding(CharsetUtil.UTF_8);
        response.setContentLength(data.length);
        response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(downloadName, "UTF-8"));
        // 写出
        ServletOutputStream outputStream = response.getOutputStream();
        IOUtils.write(data, outputStream);
    }

    public FileManage dfsDownload(String fileId) {
        // FileInfo fileInfo = fileInfoMapper.selectOne(new QueryWrapper<FileInfo>().eq("FILE_STORAGE", fileStorage));
        FileManage fileManage = this.getById(fileId);
        if (null == fileManage) {
            throw new BusinessException(BusinessErrorEnum.FILE_NOT_FOUND_ERROR);
        }
        return fileManage;
    }

    @Override
    public void viewPicById(String fileId) throws IOException {
        // FileInfo fileInfo = fileInfoMapper.selectOne(new QueryWrapper<FileInfo>().eq("FILE_STORAGE", fileStorage));
        FileManage fileManage = this.getById(fileId);
        if (null == fileManage) {
            throw new BusinessException(BusinessErrorEnum.FILE_NOT_FOUND_ERROR);
        }

        byte[] data = fastdfsUtil.download(fileManage.getFilePath());
        //获取响应对象
        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        response.setCharacterEncoding(CharsetUtil.UTF_8);
        response.setContentLength(data.length);
        response.setContentType(ContentTypeEnum.getType(fileManage.getFileSuffix()));
        // 写出
        ServletOutputStream outputStream = response.getOutputStream();
        IOUtils.write(data, outputStream);
    }


    @Override
    public void viewPicByPath(String path, String fileSuffix) throws IOException {

        byte[] data = fastdfsUtil.download(path);
        //获取响应对象
        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        response.setCharacterEncoding(CharsetUtil.UTF_8);
        response.setContentLength(data.length);
        response.setContentType(ContentTypeEnum.getType(fileSuffix));
        // 写出
        ServletOutputStream outputStream = response.getOutputStream();
        IOUtils.write(data, outputStream);
        outputStream.flush();
        outputStream.close();
        outputStream = null;
    }


    @Override
    public void downloadFiles(List<String> fileIds) throws IOException {
        String tempDir = System.getProperty("user.dir");
        //存放--服务器上zip文件的目录
        String directory = tempDir + StrUtil.BACKSLASH + Constants.SUBDIR;
        File directoryFile = new File(directory);
        if (!directoryFile.exists() || !directoryFile.isDirectory()) {
            directoryFile.mkdirs();
        }
        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd-HH-mm-ss");
        String zipFileName = formatter.format(new Date()) + ".zip";
        //设置最终输出zip文件的目录+文件名
        String strZipPath = directory + StrUtil.BACKSLASH + zipFileName;
        File zipFile = new File(strZipPath);
        try (ZipOutputStream zipStream = new ZipOutputStream(new FileOutputStream(zipFile))) {
            // List<FileInfo> fileInfoList = fileInfoMapper.selectList(new QueryWrapper<FileInfo>().in("FILE_STORAGE", fileStorages));
            List<FileManage> fileManages = this.listByIds(fileIds);
            for (FileManage fileManage : fileManages) {
                // 在压缩目录中文件的名字
                String fileName = fileManage.getFileName() + fileManage.getFileSuffix();
                ZipEntry zipEntry = new ZipEntry(fileName);
                // 定位该压缩条目位置，开始写入文件到压缩包中
                zipStream.putNextEntry(zipEntry);
                byte[] data = fastdfsUtil.download(fileManage.getFilePath());
                IOUtils.write(data, zipStream);
            }
        } catch (Exception e) {
            throw e;
        }
        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        response.setCharacterEncoding("UTF-8");
        response.setContentLengthLong(FileUtils.sizeOf(zipFile));
        response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(zipFileName, "UTF-8"));
        ServletOutputStream outputStream = response.getOutputStream();
        FileUtils.copyFile(zipFile, outputStream);
        zipFile.delete();
    }


    @Override
    @Transactional(rollbackFor = {Exception.class})
    public Boolean delete(String fileId) {
        // FileInfo fileEntity = fileInfoMapper.selectOne(new QueryWrapper<FileInfo>().eq("FILE_STORAGE", fileStorage));
        FileManage fileEntity = this.getById(fileId);
        if (null == fileEntity) {
            throw new BusinessException(BusinessErrorEnum.FILE_NOT_FOUND_ERROR);
        }
        fastdfsUtil.deleteFile(fileEntity.getFilePath());
        FileInfo fileInfo = fastdfsUtil.getFileInfo(fileEntity.getFilePath());
        if (null == fileInfo) {
            // fileInfoMapper.delete(new UpdateWrapper<FileInfo>().eq("FILE_STORAGE", fileEntity.getFileStorage()));
            this.removeById(fileId);
        }
        return fileInfo == null;
    }


    @Override
    public List<FileDeleteVo> deleteByFileIds(List<String> fileIds) {
        /*
        List<FileDeleteVo> list = new ArrayList<FileDeleteVo>();
        FileDeleteVo fileDeleteVo;
        for (String fileId : fileIds) {
            Integer result = delete(fileId) ? Constants.SUCCESS : Constants.FAIL;
            fileDeleteVo = new FileDeleteVo(fileId, result);
            list.add(fileDeleteVo);
        }
        */
        return fileIds.stream().map(fileId -> new FileDeleteVo(fileId, this.delete(fileId))).collect(Collectors.toList());
    }


    @Override
    public String getPathById(String fileId) {
        // FileInfo fileInfo = fileInfoMapper.selectOne(new QueryWrapper<FileInfo>().eq("FILE_STORAGE", fileStorage));
        FileManage fileManage = this.getById(fileId);
        return fullPath(fileManage.getId());
    }


    @Override
    public List<FilePathVo> listPathByIds(List<String> fileIds) {
        // List<FileInfo> fileInfoList = fileInfoMapper.selectList(new QueryWrapper<FileInfo>().in("FILE_STORAGE", codes));
        /*
        List<FilePathVo> pathList = new ArrayList<FilePathVo>();
        for (FileManage fileManage : fileManages) {
            String path = webPath + fileManage.getFilePath();
            pathList.add(new FilePathVo(fileManage.getFileStorage(), path));
        }
        */
        List<FileManage> fileManages = this.listByIds(fileIds);
        return fileManages.stream()
                .map(fileManage -> new FilePathVo(fileManage.getId(), fullPath(fileManage.getId())))
                .collect(Collectors.toList());
    }

    private void createFileInfo(String fileName, String fileSuffix, String filePath, String minioFileName,   long size , String id) {
        FileManage fileManage = new FileManage();
        fileManage.setId(id);
        fileManage.setName(fileName);
        fileManage.setFileName(fileName);
        fileManage.setFileSuffix(fileSuffix);
        fileManage.setFileSize(String.valueOf(size));
        fileManage.setMinioFileName(minioFileName);
        fileManage.setFilePath(filePath);
        // 获取当前登录人信息
        UserCacheData userInfo = ThreadUserContext.getCurrentCacheUser();
        if (null != userInfo) {
            fileManage.setCreatePersonCode(userInfo.getUserCode());
            fileManage.setCreatePersonName(userInfo.getUserName());
        }
        fileManageService.save(fileManage);
    }

    /**
     * 封装文件实体对象
     *
     * @param fileName
     * @param fileSuffix
     * @param filePath
     * @return
     */
    private FileManage createFileInfo(String fileName, String fileSuffix, String filePath, String id) {
        FileManage fileManage = new FileManage();
        if (StrUtil.isNotBlank(id)) {
            fileManage.setId(id);
        }
        fileManage.setFileName(fileName);
        fileManage.setFileSuffix(fileSuffix);
        fileManage.setFilePath(filePath);
        // 获取当前登录人信息
        UserCacheData userInfo = ThreadUserContext.getCurrentCacheUser();
        if (null != userInfo) {
            fileManage.setCreatePersonCode(userInfo.getUserCode());
            fileManage.setCreatePersonName(userInfo.getUserName());
        }
//        this.save(fileManage);
        return fileManage;
    }

    @Override
    public String fullPath(String simplePath) {
        return fullPath + simplePath;
    }


    @Override
    public String removeFiles(List<String> fileStorages) {
        if (CollUtil.isEmpty(fileStorages)){
            return null;
        }
        for (String fileId : fileStorages) {
            FileManage fileEntity = this.getById(fileId);
            if (null == fileEntity) {
                // 文件不存在
                continue;
            }
            StorePath storePath = StorePath.parseFromUrl(fileEntity.getFilePath());
            try {
                fastdfsUtil.deleteFile(storePath.getGroup(), storePath.getPath());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return "删除成功";
    }



    @Override
    public Boolean saveMinioUrl(List<Map<String, String>> fieldList, String tableName, String id, String string) {
        return this.getBaseMapper().saveMinioUrl(fieldList,tableName,id,string);
    }
    /**分片合并内部成员类*/
    public class FileCompleteExecutor implements Callable<Boolean> {
        private String bucketName;
        private String minioFileName;
        private String folderName;
        private String fileName;
        private String fileUid;
        private Integer partNum;
        public FileCompleteExecutor() {
        }
        public FileCompleteExecutor(String bucketName, String folderName, String fileName, String fileUid, Integer partNum,String minioFileName) {
            this.bucketName = bucketName;
            this.minioFileName = minioFileName;
            this.folderName = folderName;
            this.fileName = fileName;
            this.fileUid = fileUid;
            this.partNum = partNum;
        }

        @Override
        public Boolean call() throws Exception {
            try {
                //获取临时文件下的所有文件信息
                Iterable<Result<Item>> listObjects = minioClient.listObjects(ListObjectsArgs.builder().bucket(bucketName).prefix(folderName + "/").build());
                //计算minio中分片个数
                Integer num = 0;
                for (Result<Item> result : listObjects) {
                    num++;
                }
                //在依次校验实际分片数和预计分片数是否一致
                if (!num.equals(partNum)) {
                    log.info("文件 {} 分片合并的时候，检测到实际分片数 {} 和预计分片数 {} 不一致", folderName, num, partNum);
                    return false;
                }
                InputStream inputStream = null;
                log.info("开始合并文件 {} 分片合并，实际分片数 {} 和预计分片数 {}", folderName, num, partNum);
                for (int i = 0; i < num; i++) {
                    String tempName = folderName + "/" + fileName.substring(0, fileName.lastIndexOf(".")) + "_" + i + ".temp";
                    try {
                        //获取分片文件流
                        InputStream response = minioClient.getObject(
                                GetObjectArgs.builder().bucket(bucketName).object(tempName).build());
                        //流合并
                        if (inputStream == null) {
                            inputStream = response;
                        } else {
                            inputStream = new SequenceInputStream(inputStream, response);
                        }
                    } catch (Exception e) {
                        log.info("读取分片文件失败！", e);
                    }
                }
                if (inputStream == null) {
                    log.info("合并流数据为空！");
                    return false;
                }
                //转换为文件格式
                MockMultipartFile file = new MockMultipartFile(fileName, inputStream);
                //将合并的文件流写入到minio中
                PutObjectArgs args = PutObjectArgs.builder()
                        .bucket(bucketName).object(minioFileName)
                        .stream(file.getInputStream(), file.getSize(), -1)
//                    .contentType(file.getContentType())//这里可以不知道类型
                        .build();
                String etag = minioClient.putObject(args).etag();

                // 删除临时文件
                if (etag != null) {
                    listObjects.forEach(objectResult -> {
                        try {
                            Item item = objectResult.get();
                            minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(item.objectName()).build());
                        } catch (Exception e) {
                            log.info("删除文件夹中的文件异常", e);
                        }
                    });
                    log.info("{}:临时文件夹文件已删除！", folderName);
                }

                inputStream.close();
                // 删除redis 缓存数据
                jedisService.getTemp().delete("partCount:" + fileUid);
                log.info("{}:分片文件合并完成！", fileName);
                return true;
            } catch (Exception e) {
                log.info("合并 {} - {} 文件失败！", folderName, fileName, e);
                return false;
            }
        }
    }
    @Override
    public R filePartUploadMinio(MultipartFile file, String partFile) {
//        String objectName = Uuid.generateUniqueId(8) + "_" + file.getOriginalFilename();
        try {
            PartFileIndexVo partFileIndexVo = JSONObject.parseObject(partFile, PartFileIndexVo.class);
            String objectName = "temp/" + partFileIndexVo.getFileUid() + "/"
                    + partFileIndexVo.getFileName().substring(0, partFileIndexVo.getFileName().lastIndexOf(".")) + "_"
                    + partFileIndexVo.getPartIndex() + ".temp";
            //上传文件分片
            /**使用执行器上传分片*/ //todo 此处需要优化一下 执行器执行过程中导致分片不一致
//            ThreadPoolExecutor filePart = new ThreadPoolExecutor(10,15,2
//                    , TimeUnit.MINUTES,new ArrayBlockingQueue<>(4));
//            filePart.submit(new FilePartExecutor(file,bucketName,objectName));
            Boolean partState = minioUtils.uploadFile(file, bucketName, objectName);
            if(partState){
//                LongService.getTemp().opsForValue().increment("partCount:" + partFileIndexVo.getFileUid(),1L);
                /**上传完成是否执行合并*/
//                if (resul result = jedist.equals(partFileIndexVo.getPartTotalNum().longValue())) {
                    log.info("{}:开始合并分片请求...", partFileIndexVo.getFileName());
                    String minioFileName = partFileIndexVo.getFileName().substring(0, partFileIndexVo.getFileName().lastIndexOf("."))
                            + "_" + new Date().getTime() + partFileIndexVo.getFileName().substring(partFileIndexVo.getFileName().lastIndexOf("."));
                    /**执行器分页合并*/
                    ThreadPoolExecutor fileComplete = new ThreadPoolExecutor(10,15,10
                            , TimeUnit.MINUTES,new ArrayBlockingQueue<>(4));
                    fileComplete.submit(new FileCompleteExecutor(bucketName,
                            "temp/" + partFileIndexVo.getFileUid(),
                            partFileIndexVo.getFileName(),
                            partFileIndexVo.getFileUid(),
                            partFileIndexVo.getPartTotalNum(),minioFileName));
                    /**远程文件存储*/
                    Map<String,Object> res = new HashMap<>();
                    String fileSuffix = null;
                    res.put("fileName",minioFileName);
                    fileSuffix = partFileIndexVo.getFileName().substring(partFileIndexVo.getFileName().lastIndexOf("."));
                    long size = file.getSize();
                    String idStr = IdWorker.getIdStr();
                    this.createFileInfo(partFileIndexVo.getFileName(), fileSuffix, "" ,minioFileName ,size,idStr);
                    res.put("fileName",partFileIndexVo.getFileName());
                List<String> upload = minioUtils.upload(new MultipartFile[]{file});
                String previewFileUrl = minioUtils.getPreviewFileUrl(upload.get(0));
                    res.put("filePath",previewFileUrl);
                    res.put("id",idStr);
                    return R.ok(res);
                   /* Map<String,Object> res = minioUtils.uploadFileComplete(bucketName, "temp/" + partFileIndexVo.getFileUid(),
                            partFileIndexVo.getFileName(), partFileIndexVo.getPartTotalNum());
                    //移除文件分片上传情况，这个也应该在redis中
                    Boolean delete = false;
                    if ((Boolean) res.get("complete")) {
                        delete = jedisService.getTemp().delete("partCount:" + partFileIndexVo.getFileUid());
                        log.info("{}:分片文件合并完成！", partFileIndexVo.getFileName());
                    }*/

//                } else {
//                    return R.ok(false);
//                }
            } else {
                return R.ok(false);
            }
        } catch (Exception e) {
            log.info("文件上传异常！", e);
            return R.failed("文件上传异常！");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<FileManage> fileList(List<String> ids) {
        List<FileManage> fileManages = new ArrayList<>();
        fileManages= this.list(Wrappers.<FileManage>lambdaQuery()
                .in(FileManage::getId,ids));
        for (FileManage fileManage : fileManages) {
            String previewFileUrl = minioUtils.getPreviewFileUrl(fileManage.getMinioFileName());
            fileManage.setFilePath(previewFileUrl);
        }
        return fileManages;
    }
}
